package com.juzi;


import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;


/**
 * ATM系统入口类
 */
public class ATMSystem {
    public static void main(String[] args) {
        //1、定义账户类
        //2、定义一个集合容器，负责以后存储全部的账户对象，进行相关的业务操作
        ArrayList<Account> accounts = new ArrayList<>();
        Scanner sc = new Scanner(System.in);
        //3、展示系统的首页
        while (true) {
            System.out.println("===============ATM系统===============");

            System.out.println("1、账户登录");
            System.out.println("2、账户开户");

            System.out.println("请您选择操作");
            int command = sc.nextInt();

            switch (command) {
                case 1:
                    //用户登录
                    login(accounts, sc);
                    break;
                case 2:
                    //用户开户
                    register(accounts, sc);
                    break;
                default:
                    System.out.println("操作错误，请重新");
            }
        }

    }

    /**
     * 登录功能
     *
     * @param accounts 全部账户对象的集合
     * @param sc       扫描器
     */
    private static void login(ArrayList<Account> accounts, Scanner sc) {
        System.out.println("===============系统登录操作===============");
        //1、判断账户集合中是否存在账户，不存在，不能登录
        if (accounts.size() == 0) {
            System.out.println("当前系统中无账户，请先进行开户操作");
            return;//结束方法执行
        }

        //2、正式进入登陆操作
        while (true) {
            System.out.println("请您输入卡号");
            String CardId = sc.next();
            //3、判断卡号是否存在，根据卡号去账户集合中查询对象
            Account acc = getAccountByCardId(CardId, accounts);
            if (acc != null) {
                while (true) {
                    //卡号存在
                    //4、让用户输入密码，进行认证
                    System.out.println("请您输入密码：");
                    String PassWord = sc.next();
                    //当前账户密码是否与用户输入密码一样
                    if (acc.getPassWord().equals(PassWord)) {
                        //登陆成功
                        System.out.println("恭喜您," + acc.getUserName() + ",登录成功，您的卡号是：" + acc.getCardId());
                        //展示登陆后的操作页面
                        showUserCommand(sc,acc,accounts);
                        return;//停止登陆方法的执行
                    } else {
                        //密码不对
                        System.out.println("对不起，您输入的密码有误，请重新输入");
                    }
                }
            } else {
                System.out.println("对不起，系统中不存在该卡号，请重新输入");
            }
        }
    }

    /**
     * 展示登陆后的操作页面
     *  @param sc
     * @param acc
     * @param accounts
     */
    private static void showUserCommand(Scanner sc, Account acc, ArrayList<Account> accounts) {
        while (true) {
        System.out.println("===============用户操作页===============");
        System.out.println("1、查询账户");
        System.out.println("2、存款");
        System.out.println("3、取款");
        System.out.println("4、转账");
        System.out.println("5、修改密码");
        System.out.println("6、退出登录");
        System.out.println("7、注销账户");
        System.out.println("请选择");
        int command = sc.nextInt();
            switch (command) {
                case 1:
                    //查询账户（展示当前登录的账户信息）
                    showAccount(acc);
                    break;
                case 2:
                    //存款
                    depositMoney(acc,sc);
                    break;
                case 3:
                    //取款
                    drawMoney(acc,sc);
                    break;
                case 4:
                    //转账
                    transferMoney(sc,acc,accounts);
                    break;
                case 5:
                    //修改密码
                    updatePassWord(sc,acc);
                    return;
                case 6:
                    //退出登录
                    System.out.println("退出成功");
                    return;//停止当前方法执行

                case 7:
                    //注销账户
                    if(deleteAccount(acc,sc,accounts)){
                        //注销成功，返回首页
                    return;//让当前方法停止执行，退出

                    }else {
                        //没有注销，返回操作页面
                        break;
                    }
                default:
                    System.out.println("您输入的操作有误，请重新输入");
            }
        }
    }

    /**
     * 注销功能
     * @param acc
     * @param sc
     * @param accounts
     */
    private static boolean deleteAccount(Account acc, Scanner sc, ArrayList<Account> accounts) {
        //从当前账户集合中，删除当前账户对象
        System.out.println("===============用户注销操作===============");
        System.out.println("是否继续注销账户？是/否");
        String next = sc.next();
        switch (next) {
            case "是":
                //确认销户
                if (acc.getMoney() > 0) {
                    System.out.println("账户中有余额剩余，不建议注销");
                } else {
                    accounts.remove(acc);
                    System.out.println("账号注销完成");
                    return true;//注销成功
                }
                break;
            default:
                System.out.println("当前用户保留");
        }
        return false;
    }

    /**
     * 修改密码
     * @param sc    扫描器
     * @param acc   当前登录成功的账户对象
     */
    private static void updatePassWord(Scanner sc, Account acc) {
        System.out.println("===============用户密码修改===============");
        while (true) {
            System.out.println("请您输入当前密码");
            String PassWord = sc.next();
            //1、判断这个密码是否正确
            if (acc.getPassWord().equals(PassWord)) {
                while (true) {
                    //密码正确
                    //输入新密码
                    System.out.println("请您输入新密码");
                    String newPassWord = sc.next();

                    System.out.println("请您再次输入新密码");
                    String okPassWord = sc.next();

                    if (newPassWord.equals(okPassWord)) {
                        //两次密码相同
                        acc.setPassWord(newPassWord);
                        System.out.println("密码修改成功,请重新登陆");
                        return;
                    }else {
                        System.out.println("您输入的密码不一致");
                    }
                }
            }else{
                System.out.println("您输入的密码有误");
            }
        }
    }

    /**
     * 转账功能
     * @param sc    扫描器
     * @param acc   自己账户对象
     * @param accounts  全部账户的集合
     */
    private static void transferMoney(Scanner sc, Account acc, ArrayList<Account> accounts) {
        System.out.println("===============用户转账操作===============");
        //1、判断系统内是否存在多个账户
        if (accounts.size() < 2) {
            System.out.println("当前系统中不足两个用户，不能进行转账");
            return;
        }

        //2、判断自己账户余额是否足够
        if (acc.getMoney() == 0){
            System.out.println("对不起，当前账户余额为零");
            return;
        }

        while (true) {
            //3、真正开始转账
            System.out.println("请输入对方卡号");
            String CardId = sc.next();

            //这个卡号不能是本账户卡号
            if (CardId.equals(acc.getCardId())) {
                System.out.println("对不起，您不能给当前本卡号转账");
                continue;//结束当次执行，死循环进入下一次
            }

            //判断卡号是否存在本系统
            Account account = getAccountByCardId(CardId, accounts);
            if (account == null) {
                System.out.println("对不起，您输入的卡号不存在");
                System.out.println("是否继续");
                String next = sc.next();
                switch (next){
                    case "是":
                        break;
                    case "否":
                        return;
                }
            }else {
                //账户存在，认证姓氏
                String UserName = account.getUserName();//桔子小姐
                String tip = "*" + UserName.substring(1);
                System.out.println("请您确认收款人姓名");
                String PreName = sc.next();

                //r认证姓氏输入正确
                if (UserName.startsWith(PreName)) {
                    while (true) {
                        //认证通过，开始转帐
                        System.out.println("请输入转账金额");
                        double money = sc.nextDouble();
                        //判断余额是否足够
                        if (money > acc.getMoney()) {
                            System.out.println("对不起，您的余额不足，当前余额为：" + acc.getMoney());
                            System.out.println("是否继续");
                            String next = sc.next();
                            switch (next){
                                case "是":
                                    break;
                                case "否":
                                    return;
                            }
                        }else {
                            //余额足够，可以转账
                            acc.setMoney(acc.getMoney() - money);
                            account.setMoney(account.getMoney() + money);
                            System.out.println("转账成功，您当前余额为：" + acc.getMoney());
                            return;//结束转账方法
                        }
                    }
                }else {
                    System.out.println("对不起，您输入的信息有误");
                }
            }
        }
    }

    /**
     * 取款功能
     * @param acc   当前账户对象
     * @param sc    扫描器
     */
    private static void drawMoney(Account acc, Scanner sc) {
        System.out.println("===============用户存钱===============");
        //1、判断是否足够100元
        if (acc.getMoney() < 100){
            System.out.println("对不起，当前账户余额不足100元，不能进行取款");
            return;
        }

        while (true) {
            //2、提示用户输入取款金额
            System.out.println("请您输入取款金额");
            double money = sc.nextDouble();

            //3、判断此金额是否超出限额
            if (money > acc.getQuotaMoney()) {
                System.out.println("对不起，您当前取款金额超出本次限额，每次最多取" + acc.getQuotaMoney());
            }else {
                //没有超出限额
                //判断余额是否足够取款
                if (money > acc.getMoney()){
                    System.out.println("余额不足，当前余额为：" + acc.getMoney());
                    System.out.println("是否继续");
                    String next = sc.next();
                    switch (next){
                        case "是":
                            break;
                        case "否":
                            return;
                    }
                }else {
                    //满足所有条件，可以取钱
                    System.out.println("本次取款成功，取款" + money + "元");
                    //更新余额
                    acc.setMoney(acc.getMoney() - money);
                    //取钱结束
                    showAccount(acc);
                    return;//结束取钱
                }
            }
        }
    }

    /**
     * 存钱
     * @param acc   当前用户对象
     * @param sc    扫描器
     */
    private static void depositMoney(Account acc, Scanner sc) {
        System.out.println("===============用户存钱===============");
        System.out.println("请您输入存款金额：");
        double money = sc.nextDouble();

        //用户余额更新：原来的钱 + 存入到钱
        acc.setMoney(acc.getMoney() + money);
        System.out.println("存款成功，当前账户信息如下：");
        showAccount(acc);
    }

    /**
     * 显示账户信息
     * @param acc
     */
    private static void showAccount(Account acc) {
        System.out.println("===============当前账户信息如下===============");
        System.out.println("卡号:" + acc.getCardId());
        System.out.println("户主:" + acc.getUserName());
        System.out.println("余额:" + acc.getMoney());
        System.out.println("限额:" + acc.getQuotaMoney());
    }

    /**
     * 用户开户功能实现
     *
     * @param accounts 接收的账户集合
     * @param sc
     */
    private static void register(ArrayList<Account> accounts, Scanner sc) {
        System.out.println("===============系统开户操作===============");
        //1、创建一个账户对象，用于后期封装账户信息。
        Account account = new Account();

        //2、录入当前这个账户的信息，注入到账户对象中去
        System.out.println("请输入账户名");
        String UserName = sc.next();
        account.setUserName(UserName);

        while (true) {
            System.out.println("请输入账户密码");
            String PassWord = sc.next();
            System.out.println("请确认账户密码");
            String OkPassWord = sc.next();
            if (OkPassWord.equals(PassWord)) {
                //确认密码，注入给账户对象
                account.setPassWord(PassWord);
                break;//密码录入成功，循环结束
            } else {
                System.out.println("密码不一致，请重新输入");
            }
        }

        System.out.println("请输入本次限额");
        double QuotaMoney = sc.nextDouble();
        account.setQuotaMoney(QuotaMoney);

        //为账户随机生成一个与其他账号不重复的19位数卡号（独立功能）
        String CardId = getRandomCardId(accounts);
        account.setCardId(CardId);

        //3、把账户对象添加到账户集合中去
        accounts.add(account);
        System.out.println("恭喜您," + UserName + ",开户成功，您的卡号是：" + CardId + " 请妥善保管");

    }

    /**
     * 为账户随机生成一个与其他账号不重复的19位数卡号（独立功能）
     *
     * @return
     */
    private static String getRandomCardId(ArrayList<Account> accounts) {
        Random r = new Random();
        while (true) {
            //1、先生成19位数
            String CardId = "";
            for (int i = 0; i < 19; i++) {
                CardId += r.nextInt(10);//10 : 从0 - 9 随机生成
            }

            //2、判断这个卡号是否与其他账户卡号重复
            //根据卡号查询对象
            Account acc = getAccountByCardId(CardId, accounts);
            if (acc == null) {
                //说明卡号不重复，可以使用
                return CardId;
            }
        }
    }

    /**
     * 根据卡号查询出一个账户对象出来
     *
     * @param CardId   卡号
     * @param accounts 全部账号集合
     * @return 账号对象| null
     */
    private static Account getAccountByCardId(String CardId, ArrayList<Account> accounts) {
        for (int i = 0; i < accounts.size(); i++) {
            Account acc = accounts.get(i);
            if (acc.getCardId().equals(CardId)) {
                return acc;
            }
        }
        return null;
    }
}
